import { Callout } from '@theguild/components'

# Errors

## Custom Errors

Shield, by default, catches all errors thrown during resolver execution. This way we can be 100% sure none of your internal logic can be exposed to the client if it was not meant to be.

To return custom error messages to your client, you can return error instead of throwing it. This way, Shield knows it's not a bug but rather a design decision under control. Besides returning an error you can also return a `string` representing a custom error message.

You can return custom error from resolver or from rule itself. Rules that return error are treated as failing, therefore not processing any further resolvers.

```tsx
const typeDefs = /* GraphQL */ `
  type Query {
    customErrorInResolver: String
    customErrorInRule: String
  }
`

const resolvers = {
  Query: {
    customErrorInResolver() {
      return new Error('Custom error message from resolver.')
    },
    customErrorMessageInRule() {
      // Querying is stopped because rule returns an error
      console.log("This won't be logged.")
      return "you won't see me!"
    },
    customErrorInRule() {
      // Querying is stopped because rule returns an error
      console.log("This won't be logged.")
      return "you won't see me!"
    },
  },
}

const ruleWithCustomError = rule()(async (parent, args, ctx, info) => {
  return new Error('Custom error from rule.')
})

const ruleWithCustomErrorMessage = rule()(async (parent, args, ctx, info) => {
  return 'Custom error message from rule.'
})

const permissions = shield({
  Query: {
    customErrorInRule: ruleWithCustomError,
    customErrorMessageInRule: ruleWithCustomErrorMessage,
  },
})

const server = GraphQLServer({
  typeDefs,
  resolvers,
  middlewares: [permissions],
})
```
<Callout>
Errors thrown in resolvers can be tracked using `debug` option. This way Shield ensures your code is production ready at all times.
</Callout>

<Callout>
If you wish to see errors thrown inside resolvers, you can set `allowExternalErrors` option to `true`. This way, Shield won't hide custom errors thrown during query resolving.
</Callout>


## Global Fallback Error

GraphQL Shield allows you to set a globally defined fallback error that is used instead of `Not Authorised!` default response. This might be particularly useful for localization. You can use `string` or even custom `Error` to define it.

```ts
const permissions = shield(
  {
    Query: {
      items: allow,
    },
  },
  {
    fallbackError: 'To je napaka!', // meaning "This is a mistake" in Slovene.
  },
)

const permissions = shield(
  {
    Query: {
      items: allow,
    },
  },
  {
    fallbackError: new CustomError('You are something special!'),
  },
)

const permissions = shield(
  {
    Query: {
      items: allow,
    },
  },
  {
    async fallbackError(thrownThing, parent, args, context, info) {
      if (thrownThing instanceof ApolloError) {
        // expected errors
        return thrownThing
      }
      if (thrownThing instanceof Error) {
        // unexpected errors
        console.error(thrownThing)
        await Sentry.report(thrownThing)
        return new ApolloError('Internal server error', 'ERR_INTERNAL_SERVER')
      }
      // what the hell got thrown
      console.error('The resolver threw something that is not an error.')
      console.error(thrownThing)
      return new ApolloError('Internal server error', 'ERR_INTERNAL_SERVER')
    },
  },
)
```
